﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Linq.Expressions;

using Dapper.Library;


namespace Dapper.Library
{
    /// <summary>
    /// 查询
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Query<T> : AbstractSet, IQuery<T>
    {
        public readonly IDbConnection DbCon;
        public readonly IDbTransaction DbTransaction;

        protected DataBaseContext<T> SetContext { get; set; }

        /// <summary>
        /// 回收信息
        /// </summary>
        private void Recovery()
        {
            SqlProvider.Params = new DynamicParameters();
            SqlProvider.JoinList = new List<JoinAssTable>();
            SqlProvider.AsTableNameDic = new Dictionary<Type, string>();
        }


        protected Query(IDbConnection conn, SqlProvider sqlProvider)
        {
            SqlProvider = sqlProvider;
            DbCon = conn;
        }

        protected Query(IDbConnection conn, SqlProvider sqlProvider, IDbTransaction dbTransaction)
        {
            SqlProvider = sqlProvider;
            DbCon = conn;
            DbTransaction = dbTransaction;
        }

        public T Get()
        {

            T result;
            SqlProvider.FormatToSingle<T>();
            result = DbCon.QueryFirstOrDefaults<T>(SqlProvider, DbTransaction);

            Recovery();
            return result;
        }

        public TSource Get<TSource>()
        {
            TSource result;
            SqlProvider.FormatToSingle<T>();
            result = DbCon.QueryFirstOrDefaults<TSource>(SqlProvider, DbTransaction);

            Recovery();
            return result;
        }

        public TReturn Get<TReturn>(Expression<Func<T, TReturn>> select)
        {
            TReturn result;

            SqlProvider.Context.Set.SelectExpression = select;
            SqlProvider.FormatToSingle<T>();
            result = DbCon.QueryFirst_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public TReturn Get<TReturn>(bool where, Expression<Func<T, TReturn>> trueSelect, Expression<Func<T, TReturn>> falseSelect)
        {
            TReturn result;
            if (where)
            {
                SqlProvider.Context.Set.SelectExpression = trueSelect;
            }
            else
            {
                SqlProvider.Context.Set.SelectExpression = falseSelect;
            }
            SqlProvider.FormatToSingle<T>();
            result = DbCon.QueryFirst_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public async Task<T> GetAsync()
        {
            T result;
            SqlProvider.FormatToSingle<T>();
            result = await DbCon.QueryFirstOrDefaultAsyncs<T>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public IEnumerable<T> ToIEnumerable()
        {
            IEnumerable<T> result;
            SqlProvider.FormatToList<T>();
            result = DbCon.Querys<T>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public IEnumerable<TSource> ToIEnumerable<TSource>()
        {
            IEnumerable<TSource> result;
            SqlProvider.FormatToList<T>();
            result = DbCon.Querys<TSource>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public IEnumerable<TReturn> ToIEnumerable<TReturn>(Expression<Func<T, TReturn>> select)
        {
            IEnumerable<TReturn> result;
            SqlProvider.Context.Set.SelectExpression = select;
            SqlProvider.FormatToList<T>();
            result = DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public IEnumerable<TReturn> ToIEnumerable<TReturn>(bool where, Expression<Func<T, TReturn>> trueSelect, Expression<Func<T, TReturn>> falseSelect)
        {

            IEnumerable<TReturn> result;
            if (where){
                SqlProvider.Context.Set.SelectExpression = trueSelect;
            }
            else{
                SqlProvider.Context.Set.SelectExpression = falseSelect;
            }
            SqlProvider.FormatToList<T>();
            result = DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();

            return result;
        }

        public async Task<IEnumerable<T>> ToIEnumerableAsync()
        {
            IEnumerable<T> result;
            SqlProvider.FormatToList<T>();
            result= await DbCon.QueryAsyncs<T>(SqlProvider, DbTransaction);

            Recovery();
            return result;
        }

        public List<T> ToList()
        {
            List<T> result;
            SqlProvider.FormatToList<T>();
            result = DbCon.Querys<T>(SqlProvider, DbTransaction).ToList();

            Recovery();

            return result;
        }

        public List<TSource> ToList<TSource>()
        {
            List<TSource> result;
            SqlProvider.FormatToList<T>();
            result = DbCon.Querys<TSource>(SqlProvider, DbTransaction).ToList();

            Recovery();
            return result;
        }

        public List<TReturn> ToList<TReturn>(Expression<Func<T, TReturn>> select)
        {
            List<TReturn> result;
            SqlProvider.Context.Set.SelectExpression = select;
            SqlProvider.FormatToList<T>();
            result= DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();
            return result;
        }

        public List<TReturn> ToList<TReturn>(bool where, Expression<Func<T, TReturn>> trueSelect, Expression<Func<T, TReturn>> falseSelect)
        {
            List<TReturn> result;
            if (where)
                SqlProvider.Context.Set.SelectExpression = trueSelect;
            else
                SqlProvider.Context.Set.SelectExpression = falseSelect;
            SqlProvider.FormatToList<T>();
            result = DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);

            Recovery();
            return result;
        }

        public async Task<List<T>> ToListAsync()
        {
            List<T> result;

            SqlProvider.FormatToList<T>();
            var iEnumerable = await DbCon.QueryAsyncs<T>(SqlProvider, DbTransaction);
            result= iEnumerable.ToList();

            Recovery();
            return result;
        }

        public PageList<T> PageList(int pageIndex, int pageSize)
        {
            PageList<T> result;

            //查询总行数
            SqlProvider.FormatCount();
            var pageTotal = DbCon.QuerySingles<int>(SqlProvider, DbTransaction);
            //查询数据
            SqlProvider.FormatToPageList<T>(pageIndex, pageSize);
            var itemList = DbCon.Query_1<T>(SqlProvider, DbTransaction);
            result= new PageList<T>(pageIndex, pageSize, pageTotal, itemList);

            Recovery();
            return result;
        }

        public PageList<TSource> PageList<TSource>(int pageIndex, int pageSize)
        {
            PageList<TSource> result;

            //查询总行数
            SqlProvider.FormatCount();
            var pageTotal = DbCon.QuerySingles<int>(SqlProvider, DbTransaction);
            SqlProvider.FormatToPageList<T>(pageIndex, pageSize);
            //查询数据
            var itemList = DbCon.Query_1<TSource>(SqlProvider, DbTransaction);
            result = new PageList<TSource>(pageIndex, pageSize, pageTotal, itemList);

            Recovery();
            return result;
        }

        public PageList<TReturn> PageList<TReturn>(int pageIndex, int pageSize, Expression<Func<T, TReturn>> select)
        {
            PageList<TReturn> result;

            //查询总行数
            SqlProvider.FormatCount();
            var pageTotal = DbCon.QuerySingles<int>(SqlProvider, DbTransaction);
            //查询数据
            SqlProvider.Context.Set.SelectExpression = select;
            SqlProvider.FormatToPageList<T>(pageIndex, pageSize);
            var itemList = DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);
            result= new PageList<TReturn>(pageIndex, pageSize, pageTotal, itemList);

            Recovery();

            return result;
        }

        public PageList<TReturn> PageList<TReturn>(int pageIndex, int pageSize, bool where, Expression<Func<T, TReturn>> trueSelect, Expression<Func<T, TReturn>> falseSelect)
        {
            PageList<TReturn> result;

            //查询总行数
            SqlProvider.FormatCount();
            var pageTotal = DbCon.QuerySingles<int>(SqlProvider, DbTransaction);
            if (where)
                SqlProvider.Context.Set.SelectExpression = trueSelect;
            else
                SqlProvider.Context.Set.SelectExpression = falseSelect;
            SqlProvider.FormatToPageList<T>(pageIndex, pageSize);
            var itemList = DbCon.Query_1<TReturn>(SqlProvider, DbTransaction);

            result= new PageList<TReturn>(pageIndex, pageSize, pageTotal, itemList);

            Recovery();

            return result;
        }

        //public DataSet ToDataSet(IDbDataAdapter dataAdapter = null)
        //{
        //    DataSet result;

        //    SqlProvider.FormatToList<T>();
        //    result= DbCon.QueryDataSets(SqlProvider, DbTransaction, dataAdapter);

        //    Recovery();

        //    return result;
        //}

        //public DataSet ToDataSet<TReturn>(Expression<Func<T, TReturn>> select, IDbDataAdapter dataAdapter = null)
        //{
        //    DataSet result;

        //    SqlProvider.Context.Set.SelectExpression = select;
        //    SqlProvider.FormatToList<T>();
        //    result= DbCon.QueryDataSets(SqlProvider, DbTransaction, dataAdapter);

        //    Recovery();
        //    return result;
        //}

        //public DataSet ToDataSet<TReturn>(bool where, Expression<Func<T, TReturn>> trueSelect, Expression<Func<T, TReturn>> falseSelect, IDbDataAdapter dataAdapter = null)
        //{
        //    DataSet result;

        //    if (where)
        //        SqlProvider.Context.Set.SelectExpression = trueSelect;
        //    else
        //        SqlProvider.Context.Set.SelectExpression = falseSelect;
        //    SqlProvider.FormatToList<T>();
        //    result= DbCon.QueryDataSets(SqlProvider, DbTransaction, dataAdapter);
        //    Recovery();
        //    return result;
        //}
    }
}
